package com.game.character;

import java.util.LinkedList;
import java.util.Random;

import android.graphics.Point;

import com.game.framwork.itf.Graphics;
import com.game.tiledmap.TiledMap;

public class MonsterManager {
	private static MonsterManager manager = null;
	private int numMobs;
	private int currentWave;
	private float waveTime;
	private float monsterTime;
	private float nextWaveTime;
	private float nextMonsterTime;
	private int numMobInWave;
	private int totalMobs;
	private LinkedList<Point> listMapPos;

	private LinkedList<Monster> listMonsters;
	private LinkedList<RageMonster> listRageMonsters;
	private TiledMap tiledMap;
	
	private boolean isCreating;

	MonsterManager() {
		numMobs = 0;
		currentWave = 1;
		waveTime = 0.0f;
		monsterTime = 0.0f;

		nextWaveTime = 7.0f;
		nextMonsterTime = 2.0f;
		numMobInWave = currentWave * 2;
		totalMobs = numMobInWave;
		listMapPos = new LinkedList<Point>();
		listMonsters = new LinkedList<Monster>();
		listRageMonsters = new LinkedList<RageMonster>();
	}

	public static MonsterManager getInstance() {
		if (manager == null) {
			manager = new MonsterManager();
		}
		return manager;
	}

	public void attachMap(TiledMap tiledMap) {
		this.tiledMap = tiledMap;
	}

	public void setPos(int mapRow, int mapCol) {
		listMapPos.add(new Point(mapRow, mapCol));
	}

	public int getWave() {
		return currentWave;
	}
	
	public int getNumMobs() {
		return numMobs;
	}
	
	public LinkedList<Monster> getListMonster() {
		return listMonsters;
	}

	public LinkedList<RageMonster> getListRageMonster() {
		return listRageMonsters;
	}

	private void updateListMonsters(float deltaTime) {
		for (Monster mob : listMonsters) {
			mob.updateInternal(deltaTime);
		}
		for (RageMonster mob : listRageMonsters) {
			mob.updateInternal(deltaTime);
		}
	}

	public void update(float deltaTime) {
		waveTime += deltaTime;
		if (waveTime >= nextWaveTime) {
			waveTime = 0.0f;
			currentWave += 1;
			nextWaveTime += 3.0f;
			numMobInWave = currentWave * 2;
			totalMobs += numMobInWave;
		}

		monsterTime += deltaTime;
		if (monsterTime > nextMonsterTime) {
			if (!isCreating) {
				monsterTime = 0.0f;
				if (totalMobs > 0 && numMobs < 40) {
					createMobs();
				}
			}	
		}
		updateListMonsters(deltaTime);
	}

	public void reset() {
		currentWave = 1;
		waveTime = 0.0f;
		monsterTime = 0.0f;

		nextWaveTime = 5.0f;
		nextMonsterTime = 1.0f;
		numMobInWave = currentWave * 2;
		listMapPos = new LinkedList<Point>();
		listMonsters = new LinkedList<Monster>();
		listRageMonsters = new LinkedList<RageMonster>();
	}

	private int isHadMonster() {
		int count = listMonsters.size();
		if (count <= 0) {
			return -1;
		}
		for (int i = 0; i < count; i++) {
			if (listMonsters.get(i).isDeath) {
				return i;
			}
		}
		return -1;
	}

	private int isHadRageMonster() {
		int count = listRageMonsters.size();
		if (count <= 0) {
			return -1;
		}
		for (int i = 0; i < count; i++) {
			if (listRageMonsters.get(i).isDeath) {
				return i;
			}
		}
		return -1;
	}

	private void createMobs() {
		isCreating = true;
		Random random = new Random();
		int place = random.nextInt(listMapPos.size());
		int typeMob = random.nextInt(100);
		if (typeMob > 20) {
			int type = random.nextInt(2);
			int index = isHadMonster();
			if (index == -1) {
				Monster mob = new Monster(type);
				mob.attachTiledMap(tiledMap);
				mob.setPosInMap(listMapPos.get(place).x,
						listMapPos.get(place).y);
				listMonsters.add(mob);
				totalMobs -= 1;
				numMobs++;
				isCreating = false;
				return;
			} else {
				listMonsters.get(index).initInfo();
				listMonsters.get(index).setPosInMap(listMapPos.get(place).x,
						listMapPos.get(place).y);
				totalMobs -= 1;
				numMobs++;
				isCreating = false;
				return;
			}		
		}
		if (typeMob <= 20) {
			int type = random.nextInt(2) + 3;
			int index = isHadRageMonster();
			if (index == -1) {
				RageMonster mob = new RageMonster(type);
				mob.attachTiledMap(tiledMap);
				mob.setPosInMap(listMapPos.get(place).x,
						listMapPos.get(place).y);
				listRageMonsters.add(mob);
				totalMobs -= 1;
				numMobs++;
				isCreating = false;
				return;
			} else {
				listRageMonsters.get(index).initInfo();
				listRageMonsters.get(index).setPosInMap(listMapPos.get(place).x,
						listMapPos.get(place).y);
				totalMobs -= 1;
				numMobs++;
				isCreating = false;
				return;
			}
		}
	}

	public void paint(Graphics g) {
		for (Monster mob : listMonsters) {
			mob.paintInternal(g);
		}
		for (RageMonster mob : listRageMonsters) {
			mob.paintInternal(g);
		}
	}

	public void clear() {
		listMonsters.clear();
		listRageMonsters.clear();
	}
}
